/* 
 * File:   Scanner.cpp
 * Author: bryan
 * 
 * Created on September 6, 2013, 12:05 AM
 */

#include "Scanner.h"
#include <string>
#include <sstream>
#include <iostream>
#include <ctype.h>

using namespace std;

Scanner::Scanner(char* input) {
	input_stream.open(input);
	end = false;
	error = false;
	lineCount = 1;

	while (!end && !error) 
	{
		getNextToken();
		//end = true;
	}

	input_stream.close();
}


void Scanner::getNextToken() {

	Token temp;
		currentChar = input_stream.get(); 
			switch(currentChar) {
				case ',': createToken(lineCount, ",", "COMMA");
					break;
				case '.': createToken(lineCount, ".", "PERIOD"); 
					break;
				case '?': createToken(lineCount, "?", "Q_MARK"); 
					break;
				case '(': createToken(lineCount, "(", "LEFT_PAREN");
					break;
				case ')': createToken(lineCount, ")", "RIGHT_PAREN"); 
					break;
				case ':': checkDash();
					break;
				case '#': ignoreComment();
					break;
				case 39: createString();//'
					break;
				case 10: lineCount++;
					 break;//newline
				default: if (!input_stream.good()) {
							end = true;//EOF
						}
						else {
							if (isalpha(currentChar)) {
								checkID();
							}
							else {
								if(!isspace(currentChar))
								{
									error = true;
								}
							}
						}
					break;
			}
}

string Scanner::toString() {
	string temp = "";
	string listLength = "";
	stringstream buffer;

	if (error) {
		buffer << lineCount;
		buffer >> listLength;
		
		temp = "Error on line " + listLength;	
	}
	else {
	
		buffer << tokenList.size();
		buffer >> listLength;

		for (int lcv=0; lcv < tokenList.size(); lcv++)
		{
			temp += tokenList[lcv].toString() + "\n";
		}
	
		temp += "Total Tokens = " + listLength;
	}
	return temp;
}

void Scanner::createToken(int lineNum, string value, string type) {
	Token temp (lineNum, value, type);
	tokenList.push_back(temp);
}

void Scanner::checkDash() {
	if(input_stream.peek() == '-') {
		currentChar = input_stream.get();
		createToken(lineCount, ":-", "COLON_DASH");
	}
	else {
		createToken(lineCount, ":", "COLON");	
	}
}

void Scanner::ignoreComment() {
	while (input_stream.good() && currentChar != 10) {
		currentChar = input_stream.get();
		if (currentChar == 10) {
			input_stream.putback(currentChar);
		}
	}
}

void Scanner::createString() {
	string value = "";
	currentChar = input_stream.get();
	while(currentChar != 39 && !error) {
		if(!input_stream.good() || currentChar == 10) {
			error = true;
		}
		else {
			value += currentChar;
			currentChar = input_stream.get();
		}
	}

	createToken(lineCount, value , "STRING");

}

void Scanner::checkID() {
	string value = "";
	value += currentChar;
	char tempChar = input_stream.peek();

	while (isalpha(tempChar) || isdigit(tempChar)) {
		currentChar = input_stream.get();
		value+= currentChar;
		tempChar = input_stream.peek();
	}

	checkKeyword(value);
}

void Scanner::checkKeyword(string word) {

	if (word == "Schemes") {
		createToken(lineCount, word, "SCHEMES");
		return;
	}
	if (word == "Facts") {
		createToken(lineCount, word, "FACTS");
		return;
	}
	if (word == "Rules") {
		createToken(lineCount, word, "RULES");
		return;
	}

	if (word == "Queries") {
		createToken(lineCount, word, "QUERIES");
		return;
	}
			
	createToken(lineCount, word, "ID");	

	

}
